<template>
    <t-upload
        :draggable="type === 'draggable'"
        :theme="type === 'image' ? 'image' : 'file'"
        v-model="files"
        :action="uploadUrl"
        :max="limit"
        :multiple="limit !== 1"
        :headers="{...authHeaders, headers}"
        @success="onSuccess"
        :tips="showTip && !files.length ? tip : ''"
        :abridge-name="[6, 6]"
        :size-limit="{ size: fileSize, unit: 'MB' }"
        :format-response="formatResponse"
        allow-upload-duplicate-file
        :before-upload="beforeUpload"
        @fail="handleFail"/>
</template>

<script setup lang="ts">
import {t} from "@/locales";
import {MessagePlugin, SuccessContext, UploadFailContext, UploadFile, UploadProps} from "tdesign-vue-next";
import {PropType, ref, watch} from "vue";
import {useUserStore} from "@/store";
import {fileView, uploadUrl} from "@/api/upload";

const user = useUserStore();
const files = ref<UploadProps['files']>([]);
const emit = defineEmits(['update:value']);
const authHeaders = { [user.tokenHead]: user.token };

const props = defineProps({
    uploadUrl: {
        type: String,
        default: uploadUrl
    },
    headers: {
        type: Object,
        default: {}
    },
    type: {
        type: String as PropType<'draggable' | 'image' | 'button'>,
        default: 'image'
    },
    valueType: {
        // value  json: [{ name: '文件名', data: '后端返回的数据' }], string: "[{ name: '文件名', data: '后端返回的数据' }]", data: 后端返回的数据，以逗号分割
        type: String as PropType<'json' | 'string' | 'data'>,
        default: 'string'
    },
    value: [String, Array],
    // 图片数量限制
    limit: {
        type: Number,
        default: 5,
    },
    // 大小限制(MB)
    fileSize: {
        type: Number,
        default: 5,
    },
    // 文件类型, 例如['png', 'jpg', 'jpeg']
    fileType: {
        type: Array,
        default: () => ["png", "jpg", "jpeg"],
    },
    // 是否显示提示
    showTip: {
        type: Boolean,
        default: true
    },
    tip: {
        type: String,
        default: t('components.upload.tips')
    }
});

watch(() => props.value, (val: string) => {
    if (val) {
        if (props.valueType == 'json') {
            files.value = val;
        } else if (props.valueType == 'string') {
            files.value = JSON.parse(val).filter(i => {
                i.url = fileView(i.data);
                return true;
            });
        } else {
            // 首先将值转为数组
            const list = val.split(',');
            // 然后将数组转为对象数组
            files.value = list.map(item => {
                if (typeof item === "string") {
                    let url;
                    if (item.startsWith('http')) {
                        url = item;
                    } else {
                        url = fileView(item);
                    }
                    item = {name: item, url, data: item};
                }
                return item;
            });
        }
    } else {
        files.value = [];
    }
}, { immediate: true, deep: true });


const handleFail = (options: UploadFailContext) => {
    MessagePlugin.error(t('components.upload.error'));
}

/**
 * 文件上传前校验
 * @param file
 */
const beforeUpload = (file: UploadFile) => {
    let isImg = false;
    if (props.fileType && props.fileType.length) {
        let fileExtension = "";
        if (file.name.lastIndexOf(".") > -1) {
            fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1);
        }
        isImg = props.fileType.some(type => {
            if (file.type.indexOf(type) > -1) return true;
            return !!(fileExtension && fileExtension.indexOf(type) > -1);
        });
    }
    if (!isImg) {
        MessagePlugin.error(`${t('components.upload.fileType')}: ${props.fileType.join("、")}!`);
        return false;
    }
    if (props.fileSize) {
        const isLt = file.size / 1024 / 1024 < props.fileSize;
        if (!isLt) {
            MessagePlugin.error(`${t('components.upload.fileSize')} ${props.fileSize} MB!`);
            return false;
        }
    }
    return true;
}

const onSuccess = (context: SuccessContext) => {
    let data;
    if (props.valueType == 'json') {
        data = context.fileList.map(i => {
            const data = { name: i.name, data: i.data };
            if (!data.data && i.response.data) {
                data.data = i.response.data;
            }
            return data;
        });
    } else if (props.valueType == 'string') {
        const list = context.fileList.map(i => {
            const data = { name: i.name, data: i.data };
            if (!data.data && i.response.data) {
                data.data = i.response.data;
            }
            return data;
        });
        data = JSON.stringify(list);
    } else {
        data = context.fileList.map(i => i.response.data).join(',');
    }
    emit('update:value', data);
}

/**
 * 用于格式化接口响应值，error 会被用于上传失败的提示文字；url 表示文件/图片地址
 * @param res
 */
const formatResponse = (res: any) => {
    if (res.code != 200) {
        return { ...res, error: res.message };
    }
    return {...res, url: fileView(res.data)};
}

</script>
